今天我們長話短說,Composite模式主要是希望可以透過同樣的型式對每個物件做操作,並且在操控的物件中是有保持著一種層級關係。以今天的例子來說,我想要只透過一個抽象類別,去表示出老闆以及他的下屬或者更下層階級的關係,就可以使用 Composite模式。
將物件以樹形結構組織起來,以達成「部分-整體」的層次結構,使得用戶端對單個物件和組合物件的使用具有一致性。
(圖片來源:https://en.wikipedia.org/wiki/Composite_pattern#/media/File:Composite_UML_class_diagram_(fixed).svg)
EmployeeComponent
為抽象類別,也就是所有人的基底,不管事老闆或者下屬,都是透過Employee
去繼承這個抽象類別,可以看到裡面有一個屬性Subordinates
是List<EmployeeComponent>
,代表了這個抽象類別會再去聚合它自己,因此才能達到階層的關係。using System;
using System.Collections.Generic;
using System.Linq;
namespace DAY22_Composite
{
internal class Program
{
static void Main(string[] args)
{
Employee CEO = new Employee("Howard", "CEO", 30000);
Employee headSales = new Employee("Sandy", "Head Sales", 20000);
Employee headMarketing = new Employee("Sue", "Head Marketing", 20000);
Employee salesExecutive1 = new Employee("Richard", "Sales", 10000);
Employee salesExecutive2 = new Employee("Johnson", "Sales", 10000);
Employee marketingExecutive1 = new Employee("Leo", "Marketing", 10000);
Employee marketingExecutive2 = new Employee("Bob", "Marketing", 10000);
Employee clerk1 = new Employee("clerk1", "base", 100);
Employee clerk2 = new Employee("clerk2", "base", 100);
// 一層包一層
CEO.Add(headSales);
CEO.Add(headMarketing);
headSales.Add(salesExecutive1);
headSales.Add(salesExecutive2);
headMarketing.Add(marketingExecutive1);
headMarketing.Add(marketingExecutive2);
marketingExecutive1.Add(clerk1);
marketingExecutive2.Add(clerk2);
var subordinates = CEO.GetSubordinates();
// 查看 CEO 所有的下屬以及階層關係
Show(subordinates, CEO.Name);
}
public static void Show(List<EmployeeComponent> employees, string bossName, int level = 1)
{
int _level = level;
foreach (var x in employees.Select((value, index) => new { index, value }))
{
// 使用遞迴做 List 輸出
Console.WriteLine($"下屬第{_level}階 |直屬上司: {bossName} |姓名:{x.value.Name}, 部門:{x.value.Dept}, 薪水:${x.value.Salary}");
Show(x.value.Subordinates, x.value.Name, ++_level);
--_level;
}
}
}
public abstract class EmployeeComponent
{
public string Name { get; set; }
public string Dept { get; set; }
public int Salary { get; set; }
public List<EmployeeComponent> Subordinates { get; set; }
public abstract void Add(EmployeeComponent employee);
public abstract void Remove(EmployeeComponent employee);
public abstract List<EmployeeComponent> GetSubordinates();
}
public class Employee : EmployeeComponent
{
public Employee(string name, string dept, int salary)
{
Name = name;
Dept = dept;
Salary = salary;
Subordinates = new List<EmployeeComponent>();
}
public override void Add(EmployeeComponent employee)
{
Subordinates.Add(employee);
}
public override void Remove(EmployeeComponent employee)
{
Subordinates.Remove(employee);
}
public override List<EmployeeComponent> GetSubordinates()
{
return Subordinates;
}
}
}
透過 Composite模式,我們可以在抽象類別中再去聚合自己,因此不用在乎究竟要處理的物件是一種個體物件或者是組成物件,都只要針對其所定義的一致介面進行操作即可。